package org.example.demo3.demos.web.asepect;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.example.demo3.demos.web.annotation.Translate;
import org.example.demo3.demos.web.common.Result;
import org.example.demo3.demos.web.service.translate.TranslateService;
import org.example.demo3.demos.web.service.translate.impl.TranslateMap;
import org.example.demo3.demos.web.utils.ObjConvertUtils;
import org.example.demo3.demos.web.utils.StringUtil;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@Aspect // 定义一个切面
@Component // 做成组件类
@Slf4j // 好像是日志
public class TranslateAspect {
    @Pointcut("execution(* org.example.demo3.demos.web.*.controller.*Controller.*(..))") // 指定切点位置,就是文件的路径.
    public void excudeService() { //
    }
    // 切点实现
    @Around("excudeService()") // 切点实现
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        //这是定义开始事件
        long time1 = System.currentTimeMillis();
        //这是方法并获取返回结果
        Object result = pjp.proceed();
        //这是获取到 结束时间
        long time2 = System.currentTimeMillis();
        log.debug("获取JSON数据 耗时：" + (time2 - time1) + "ms");
        //解析开始时间
        long start = System.currentTimeMillis();
        //开始解析（翻译字段内部的值 这玩意的都会被翻译）
        this.parseText(result);
        //解析结束时间
        long end = System.currentTimeMillis();
        log.debug("解析注入JSON数据  耗时" + (end - start) + "ms");
        return result;
    }
    private void parseText(Object result) {
        if (result instanceof Result) {
            List<JSONObject> items = new ArrayList<>();
            Object data = ((Result<?>) result).getData();
            if (data == null) {
                log.debug("data为null不做处理");
                return;
            }
            // 如果是 page
            if (data instanceof Page) {
                IPage page = (IPage) data;
                //循环查找出来的数据
                for (Object record : page.getRecords()) {
                    JSONObject item = getItem(record);
                    items.add(item);
                }
                page.setRecords(items);
            } else if (data instanceof List) {
                // 如果是 List
                List list = (List) data;
                for (Object o : list) {
                    if (!(o instanceof Long)
                            && !(o instanceof Integer)
                            && !(o instanceof Boolean)
                            && !(o instanceof Double)
                            && !(o instanceof Float)
                            && !(o instanceof Byte)
                            && !(o instanceof Short)
                            && !(o instanceof Character)
                            && !(o instanceof String)
                            && !(o instanceof File)) {
                        JSONObject item = getItem(o);
                        items.add(item);
                    }
                }
                if (CollectionUtil.isNotEmpty(items)) {
                    ((Result<List>) result).setData(items);
                }
            } else if (!(data instanceof Long)
                    && !(data instanceof Integer)
                    && !(data instanceof Boolean)
                    && !(data instanceof Double)
                    && !(data instanceof Float)
                    && !(data instanceof Byte)
                    && !(data instanceof Short)
                    && !(data instanceof Character)
                    && !(data instanceof String)
                    && !(data instanceof File)) {
                ((Result<JSONObject>) result).setData(getItem(data));
            }
        }
    }
    private static JSONObject getItem(Object o) {
        ObjectMapper mapper = new ObjectMapper();
        // null替换为""
        mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException {
                arg1.writeString("");
            }
        });
        String json = "{}";
        try {
            //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
            json = mapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            log.error("json解析失败" + e.getMessage(), e);
        }
        JSONObject item = JSONObject.parseObject(json);

        for (Field field : ObjConvertUtils.getAllFields(o)) {
            if (field.getAnnotation(Translate.class) != null) {
                // 翻译类型
                String type = field.getAnnotation(Translate.class).type();
                // 字典编码
                String code = field.getAnnotation(Translate.class).value();
                // 翻译后缀
                String text = field.getAnnotation(Translate.class).translateText();
                // 日期格式
                String format = field.getAnnotation(Translate.class).format();
                // 获取当前待翻译的值
                String key = StringUtil.toString(item.get(field.getName()));

                String textValue = "";
                TranslateService translateMap = TranslateMap.getTranslateMap(type);
                textValue = translateMap.translate(type, code, format, key);
                if (StringUtil.isEmpty(textValue)) {
                    textValue = key;
                }
                //翻译字典值对应的txt
                item.put(field.getName() + text, textValue);
            }
        }
        return item;
    }

}
